#ifndef CONFIG_H
#define CONFIG_H

#include <map>
#include <vector>
#include <memory>
#include <string>
#include <iostream>
#include <any>
#include <glm/glm.hpp>

// 支持加载vec3, string, float
class Config
{
public:
    Config() { }

    template <typename T>
    void add_config(std::string name);

    template <typename T>
    bool get_config(T& t, const std::string name) const;

    bool load_config(std::string filename);
    bool is_all_loaded() const;

private:

    bool load_vec3(std::fstream &fin, std::any &value) const;
    bool load_string(std::fstream &fin, std::any &value) const;
    bool load_float(std::fstream &fin, std::any &value) const;
    
    struct Content {
        std::any v;
        bool load_state;

        Content(): load_state(false) {}

        Content(std::any v): v(v), load_state(false) {}
    };

    std::map<std::string, Content> data;
    std::vector<std::string> keys;
};

template <typename T>
void Config::add_config(std::string name)
{
    keys.push_back(name);
    data[name] = Content(std::make_any<T>());
}

template <typename T>
bool Config::get_config(T& t, const std::string name) const
{
    if(data.find(name) == data.end())
    {
        std::cout << "Error: Config " << name << " not found!\n";
        return false;
    }
    const Content& content = data.find(name)->second;
    if(!content.load_state)
    {
        std::cout << "Error: Config " << name << " not loaded!\n";
        return false;
    }
    try
    {
        t = std::any_cast<T>(content.v);
        return true;
    }
    catch(const std::bad_any_cast& e)
    {
        std::cout << "Error: Config type not matched!\n";
        return false;
    }
    
}

#endif